package com.project.ivl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.project.frame.common.annotation.LogIgnore;
import com.project.frame.common.model.BaseResp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/**
 * desc
 *
 * @author cjq
 * @date 2023-11-02
 */
@RestController
@RequestMapping("/iv")
@Slf4j
public class IvController {


    @PostMapping(value = "to")
    @LogIgnore
    public BaseResp to(@RequestBody String json)
            throws Exception {
        InputStream inputStream = null;
        File outputFile = null;
        File outFile = null;
        try{

            String str = "Android-2222" ;
            JSONObject jSONObject = new JSONObject();
            JSONObject jSONObject2 = new JSONObject();
            jSONObject2.put("x", 10);
            jSONObject2.put("y", 10);
            jSONObject2.put("width",-10);
            jSONObject2.put("height", -10);
            jSONObject.put("sdkVer", str);
            jSONObject.put("faceRect", jSONObject2);
            jSONObject.put("time", siv());
            String jSONObject3 = jSONObject.toString();

            JSONObject obj = JSONObject.parseObject(json);

            String base64String = obj.getString("base64");
            String userDir = System.getProperty("user.dir");
            String tmpPath = userDir+File.separatorChar+"ivTemp"+File.separatorChar;

            File tmpPathDir = new File(tmpPath);
            tmpPathDir.mkdirs();

            String filePath = tmpPath+"a-"+IdUtil.simpleUUID() +".jpg";

            byte[] imageBytes = java.util.Base64.getDecoder().decode(base64String);

            // 创建文件输出流
            outputFile = new File(filePath);
            try (FileOutputStream fos = new FileOutputStream(filePath)) {
                fos.write(imageBytes);
            }

            byte[] ivl2 = ivl(jSONObject3);
            byte[] bArr = new byte[ivl2.length + 32];
            System.arraycopy(ivl(), 0, bArr, 0, 32);
            System.arraycopy(ivl2, 0, bArr, 32, ivl2.length);
            String str2 = "IVL-" + str + ";" + java.util.Base64.getEncoder().encodeToString(bArr);


            JpegImageMetadata metadata = (JpegImageMetadata) Imaging.getMetadata(outputFile);
            TiffImageMetadata exif = metadata.getExif();
            // 设置或更新 "Software" 属性
            TiffOutputSet outputSet = exif.getOutputSet();

            final TiffOutputDirectory rootDirectoryt=outputSet.getOrCreateRootDirectory();

            rootDirectoryt.removeField(TiffTagConstants.TIFF_TAG_SOFTWARE);
            rootDirectoryt.add(TiffTagConstants.TIFF_TAG_SOFTWARE,str2);
            //写入后，保存
            String outFileName = tmpPath+"b-"+IdUtil.simpleUUID()+".jpg";
            outFile = new File(outFileName);
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outFile));
            new ExifRewriter().updateExifMetadataLossless(outputFile, bos, outputSet);
//            ==============================

            int length = (int) outputFile.length();
            byte[] bArr2 = new byte[length];
            DataInputStream dataInputStream = new DataInputStream(new FileInputStream(outFileName));
            dataInputStream.readFully(bArr2);
            dataInputStream.close();

            byte[] bytes = str2.getBytes(StandardCharsets.UTF_8);
            int ivl3 = ivl(bArr2, bytes);
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(bArr2, 0, ivl3);
            messageDigest.update(bArr2, bytes.length + ivl3, (length - ivl3) - bytes.length);
            messageDigest.update(jSONObject3.getBytes(StandardCharsets.UTF_8));
            System.arraycopy(messageDigest.digest(), 0, bArr, 0, 32);
            System.arraycopy(("IVL-" + str + ";" + Base64.getEncoder().encodeToString(bArr)).getBytes(StandardCharsets.UTF_8), 0, bArr2, ivl3, bytes.length);

            String result = Base64.getEncoder().encodeToString(bArr2);

            try{
                bos.close();
            }catch(Exception e){
                e.printStackTrace();
            }
            return BaseResp.renderSuccess(result);
        }catch(Exception e){
            e.printStackTrace();
            return BaseResp.renderFail(0,e.getMessage());
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if(outFile!=null){
                    outFile.delete();
                }
                if(outputFile!=null){
                    outputFile.delete();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static byte[] ivl(String str) throws Exception {
        SecretKeySpec secretKeySpec = new SecretKeySpec(new byte[]{-126, 82, -86, 58, Byte.MIN_VALUE, -50, -117, 31, -116, -53, -125, -87, 52, 46, -26, -38, 101, -108, -48, -31, -107, -81, 108, 43, -53, 4, -62, 56, -26, 91, -36, -80}, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(1, secretKeySpec, new IvParameterSpec(new byte[]{-33, 28, 5, -122, 17, 67, -25, 51, 41, -81, 96, -124, 70, -34, 95, -94}));
        return cipher.doFinal(str.getBytes(StandardCharsets.UTF_8));
    }

    private static String siv() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+08"));
        Date now = new Date();
        now = DateUtil.parse("2023-11-06 10:30:00","yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(now);
    }
    private static byte[] ivl() {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(siv().getBytes(StandardCharsets.UTF_8));
            return messageDigest.digest();
        } catch (Exception e) {
            e.printStackTrace();
            return new byte[32];
        }
    }

    private static int ivl(byte[] bArr, byte[] bArr2) {
        boolean z;
        for (int i = 0; i < bArr.length - bArr2.length; i++) {
            int i2 = 0;
            while (true) {
                if (i2 >= bArr2.length) {
                    z = true;
                    break;
                } else if (bArr[i + i2] != bArr2[i2]) {
                    z = false;
                    break;
                } else {
                    i2++;
                }
            }
            if (z) {
                return i;
            }
        }
        return -1;
    }


}
